<template>
  <!-- 通用确认弹窗 -->
  <ElDialog
    :model-value="show"
    class="confirm-dialog"
    :width="width"
    :show-close="false"
    append-to-body
    align-center
    :close-on-click-modal="closeOnClickModal"
    :close-on-press-escape="closeOnPressEscape"
    @close="closeHandler"
  >
    <div class="main">
      <!-- 主体 -->
      <div class="shim">
        <div class="title">
          <slot name="title">
            <component
              :is="title"
              v-if="typeof title === 'function'"
            ></component>
            <template v-else>
              {{ title }}
            </template>
          </slot>
        </div>
        <div class="content">
          <slot>
            <component
              :is="content"
              v-if="typeof content === 'function'"
            ></component>
            <template v-else>
              {{ content }}
            </template>
          </slot>
        </div>
        <div class="footer" :reverse="reverse">
          <slot
            name="footer"
            :cancelHandler="cancelHandler"
            :confirmHandler="confirmHandler"
            :loading="loading"
          >
            <ElButton
              v-if="!hiddenCancel"
              class="btn cancel-btn"
              btnHover
              @click="cancelHandler"
              >{{
                typeof cancelText === "function" ? cancelText() : cancelText
              }}</ElButton
            >
            <ElButton
              type="primary"
              class="btn confirm-btn"
              :loading="loading"
              @click="confirmHandler"
              >{{
                typeof confirmText === "function" ? confirmText() : confirmText
              }}</ElButton
            >
          </slot>
        </div>
      </div>

      <!-- 关闭按钮 -->
      <div v-if="showClose" class="close-box" @click="close()">
        <ElIcon :size="22"><Close /></ElIcon>
      </div>
    </div>
  </ElDialog>
</template>
<script lang="ts" setup>
import { Close } from "@element-plus/icons-vue";

const props = withDefaults(
  defineProps<{
    show: boolean;
    showClose?: boolean;
    onClose?: (status?: boolean) => void;
    // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
    onCancel?: () => void | Promise<boolean | void>;
    // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
    onConfirm?: () => void | Promise<boolean | void>;
    title?: string | (() => VNode);
    content?: string | (() => VNode);
    cancelText?: string | (() => VNode);
    confirmText?: string | (() => VNode);
    /** 是否隐藏取消按钮 */
    hiddenCancel?: boolean;
    width?: number | string;
    /** 反转按钮位置 */
    reverse?: boolean;
    /** 按下 ESC 是否关闭 */
    closeOnPressEscape?: boolean;
    /** 点击遮罩是否关闭 */
    closeOnClickModal?: boolean;
    /** 是否使用确认按钮loading */
    useLoading?: boolean;
  }>(),
  {
    showClose: true,
    cancelText: "取消",
    confirmText: "确定",
    hiddenCancel: false,
    width: 418,
    reverse: false,
    closeOnPressEscape: true,
    closeOnClickModal: true,
  },
);

const emits = defineEmits<(e: "update:show", value: boolean) => void>();

defineOptions({
  inheritAttrs: false,
});

const showLoading = ref(false);

const loading = computed(() => {
  return props.useLoading && showLoading.value;
});

/**
 * @param status 是否是确认导致关闭的
 */
const close = (status?: boolean) => {
  console.log("close", status);
  emits("update:show", false);
  props.onClose?.(status);
};

const cancelHandler = async () => {
  const res = await props.onCancel?.();
  if (res === false) {
    console.log("确认弹窗 onCancel 返回false，不关闭弹窗");
    return;
  }
  close(false);
};

const confirmHandler = async () => {
  showLoading.value = true;
  try {
    const res = await props.onConfirm?.();
    showLoading.value = false;
    if (res === false) {
      console.log("确认弹窗 onConfirm 返回false，不关闭弹窗");
      return;
    }
    close(true);
  } catch (error) {
    showLoading.value = false;
  }
};

const closeHandler = () => {
  console.log("closeHandler");
  close(false);
};
</script>
<style lang="less" scoped>
.confirm-dialog {
  .content {
    overflow-x: hidden;
    overflow-y: auto;
    max-height: calc(100vh - 200px);
  }
  .btn {
    width: 150px;
    height: 40px;
    border-radius: 4px;
  }
  .main {
    // padding: 33px 44px 20px;
    position: relative;
    text-align: center;

    .close-box {
      position: absolute;
      top: 0;
      right: 0;
      cursor: pointer;
      z-index: 2;
    }

    .shim {
      position: relative;
      z-index: 1;

      .title {
        font-size: 18px;
        font-weight: 500;
      }

      .content {
        font-size: 16px;
        margin-top: 15px;
      }

      .footer {
        display: flex;
        justify-content: center;
        align-items: center;
        padding-top: 5px;
        & > .btn:not(:last-child) {
          margin-right: 30px;
        }
        &[reverse="true"] {
          flex-direction: row-reverse;
          & > .btn:not(:last-child) {
            margin-right: 0;
            margin-left: 30px;
          }
        }
      }
    }
  }
}
</style>
<style lang="less">
.confirm-dialog {
  .el-dialog__header,
  .el-dialog__body {
    padding: 0;
    background-color: transparent;
  }
}
</style>
